﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;

namespace Business_Layer
{
    [Serializable]
    public class Mindmap
    {
        public enum StepType
        {
            UndoStep,
            RedoStep
        }

        public Mindmap(string name)
        {
            this.name = name;
            initialize();
        }

        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }


        private List<Component> components;
        private List<Step> steps;

        private int width, height;
        private int currentStepCount;

        private Bitmap screen;

        /// <summary>
        /// Initiates a new mindmap.
        /// </summary>
        private void initialize()
        {
            components = new List<Component>();
            steps = new List<Step>();
            width = 800;
            height = width / 4 * 3;
            currentStepCount = -1;

            screen = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(screen))
            {
                g.Clear(Color.White);
            }
        }

        /// <summary>
        /// Adds a body to this mindmap instance.
        /// </summary>
        /// <param name="sx">The X Coordinate to start.</param>
        /// <param name="sy">The Y Coordinate to start.</param>
        /// <param name="ex">The X Coordinate to end.</param>
        /// <param name="ey">The Y Coordinate to end.</param>
        /// <param name="text">The text for the body.</param>
        /// <param name="color">The color for this component.</param>
        public void AddBody(int sx, 
                            int sy, 
                            int ex, 
                            int ey, 
                            string text,
                            Color color)
        {
            components.Add(new Body(sx, sy, ex, ey, text, color));
            Update();
        }

        /// <summary>
        /// Adds a relation between 2 components in this mindmap instance.
        /// </summary>
        /// <param name="component1">First component selected.</param>
        /// <param name="component2">Second component seletected.</param>
        /// <param name="text">The relations' name.</param>
        public void AddRelation(Component component1,
                                Component component2,
                                string text)
        {
            components.Add(new Relation(component1, component2, text));
            Update();
        }

        /// <summary>
        /// Adds a picture to this mindmap instance.
        /// </summary>
        /// <param name="xPos">The X Coordinate to start.</param>
        /// <param name="yPos">The Y Coordinate to start.</param>
        /// <param name="width">The components width.</param>
        /// <param name="height">The components height.</param>
        /// <param name="text">The pictures' name.</param>
        /// <param name="picture">A Bitmap as picture.</param>
        public void AddPicture(int xPos,
                               int yPos,
                               int width,
                               int height,
                               string text,
                               Bitmap picture)
        {
            components.Add(new Picture(xPos, yPos, width, height, text, picture));
            Update();
        }

        /// <summary>
        /// Update the steps.
        /// </summary>
        public void Update()
        {
            steps.Add(new Step(components));
            currentStepCount++;
        }

        /// <summary>
        /// Set the current step direction.
        /// </summary>
        /// <param name="step">Direction.</param>
        public void SetStep(StepType step)
        {
            switch (step)
            {
                case StepType.UndoStep:
                    if (currentStepCount - 1 >= 0)
                    {
                        currentStepCount--;
                        Console.WriteLine(currentStepCount);
                        components = new List<Component>(steps.ElementAt(currentStepCount).GetStep());
                    }
                    break;
                case StepType.RedoStep:
                    if (currentStepCount + 1 < steps.Count)
                    {
                        currentStepCount++;
                        Console.WriteLine(currentStepCount);
                        components = new List<Component>(steps.ElementAt(currentStepCount).GetStep());
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Draw the mindmap to a screen.
        /// </summary>
        /// <returns></returns>
        public Bitmap Draw()
        {
            using (Graphics g = Graphics.FromImage(screen))
            {
                g.Clear(Color.White);
                for (int i = 0; i < components.Count; i++)
                {
                    if (components[i] is Relation)
                    {
                        components[i].Draw(g);
                    }
                } 
                for (int i = 0; i < components.Count; i++)
                {
                    if (!(components[i] is Relation))
                    {
                        components[i].Draw(g);
                    }
                }
            }
            return screen;
        }

        /// <summary>
        /// Preview a component.
        /// </summary>
        /// <param name="typeComponent">Type</param>
        /// <param name="sx">The X Coordinate to start.</param>
        /// <param name="sy">The Y Coordinate to start.</param>
        /// <param name="ex">The X Coordinate to end.</param>
        /// <param name="ey">The Y Coordinate to end.</param>
        /// <param name="color">The color to preview.</param>
        /// <returns></returns>
        public Bitmap PreviewComponent(TypeComponent typeComponent, int sx, int sy, int ex, int ey, Color color)
        {
            Component preview;
            Bitmap previewScreen = new Bitmap(screen);

            //Moet weg kunnen later
            preview = new Body(sx, sy, ex, ey, "", color);

            switch (typeComponent)
            {
                case TypeComponent.Body:
                    preview = new Body(sx, sy, ex, ey, "", color);
                    break;
                case TypeComponent.Relation:
                    preview = new Relation(new Body(sx, sy, sx, sy, "", Color.White), new Body(ex, ey, ex, ey, "", Color.White), "");
                    break;
                case TypeComponent.Picture:
                    preview = new Body(sx, sy, ex, ey, "", Color.White);
                    break;
                default:
                    break;
            }
            using (Graphics g = Graphics.FromImage(previewScreen))
            {
                preview.Draw(g);
            }

            return previewScreen;
        }

        /// <summary>
        /// Returns a list with all components.
        /// </summary>
        public List<Component> GetComponents
        {
            get { return components; }
        }

        /// <summary>
        /// Returns the current mindmap screen.
        /// </summary>
        /// <returns></returns>
        public Bitmap GetScreen()
        {
            return screen;
        }

        /// <summary>
        /// Moves a component into a certain direction.
        /// </summary>
        /// <param name="componentId">Id of component to move.</param>
        /// <param name="dx">Direction X.</param>
        /// <param name="dy">Direction Y.</param>
        public void MoveComponent(int componentId, int dx, int dy)
        {
            components[componentId].Move(dx, dy);
        }
    }
}
